import java_cup.runtime.Symbol;

%%

%class Lexer
%cup
%implements sym
%line
%column


%{
	StringBuffer string = new StringBuffer();

	private Symbol symbol(int sym) {
		return new Symbol(sym, yyline+1, yycolumn+1);
	}
  
  	private Symbol symbol(int sym, Object val) {
    	return new Symbol(sym, yyline+1, yycolumn+1, val);
  	}

  	private void error(String message) {
    	System.out.println("Error at line "+(yyline+1)+", column "+(yycolumn+1)+" : "+message);
  	}
%} 


D 						= [0-9]
L 						= [a-zA-Z_]
H 						= [a-fA-F0-9]
E 						= [Ee][+-]?{D}+
FS 						= (f|F|l|L)
IS 						= (u|U|l|L)*

TraditionalComment		= "/*" [^*] ~"*/" | "/*" "*"+ "/"

LineTerminator 			= \r|\n|\r\n

InputCharacter 			= [^\r\n]

EndOfLineComment 		= "//" {InputCharacter}* {LineTerminator}

DocumentationComment	= "/**" {CommentContent} "*"+ "/"

CommentContent 			= ( [^*] | \*+ [^/*] )*

Comment 				= {TraditionalComment} | {EndOfLineComment} | {DocumentationComment}

constante				= 0[xX]{H}+{IS}? | 0{D}+{IS}? | {D}+{IS}? | L?'(\\.|[^\\'])+' | {D}+{E}{FS}? | {D}*"."{D}+({E})?{FS}? | {D}+"."{D}*({E})?{FS}?  		

new_line 				= \r|\n|\r\n

white_space 			= {new_line} | [ \t\f]

ident  					= {L}({L}|{D})*

%state STRING

%%

/* names */
<YYINITIAL> {

\"						{ string.setLength(0); yybegin(STRING); }
"auto"					{ return symbol(AUTO); }
"break"					{ return symbol(BREAK); }
"case"					{ return symbol(CASE); }
"char"					{ return symbol(CHAR); }
"const"					{ return symbol(CONST); }
"continue"				{ return symbol(CONTINUE); }
"default"				{ return symbol(DEFAULT); }
"do"					{ return symbol(DO); }
"double"				{ return symbol(DOUBLE); }
"else"					{ return symbol(ELSE); }
"enum"					{ return symbol(ENUM); }
"extern"				{ return symbol(EXTERN); }
"float"					{ return symbol(FLOAT); }
"for"					{ return symbol(FOR); }
"goto"					{ return symbol(GOTO); }
"if"					{ return symbol(IF); }
"int"					{ return symbol(INT); }
"long"					{ return symbol(LONG); }
"register"				{ return symbol(REGISTER); }
"return"				{ return symbol(RETURN); }
"short"					{ return symbol(SHORT); }
"signed"				{ return symbol(SIGNED); }
"sizeof"				{ return symbol(SIZEOF); }
"static"				{ return symbol(STATIC); }
"struct"				{ return symbol(STRUCT); }
"switch"				{ return symbol(SWITCH); }
"typedef"				{ return symbol(TYPEDEF); }
"union"					{ return symbol(UNION); }
"unsigned"				{ return symbol(UNSIGNED); }
"void"					{ return symbol(VOID); }
"volatile"				{ return symbol(VOLATILE); }
"while"					{ return symbol(WHILE); }
"..."					{ return symbol(ELLIPSIS); }
">>="					{ return symbol(RIGHT_ASSIGN); }
"<<="					{ return symbol(LEFT_ASSIGN); }
"+="					{ return symbol(ADD_ASSIGN); }
"-="					{ return symbol(SUB_ASSIGN); }
"*="					{ return symbol(MUL_ASSIGN); }
"/="					{ return symbol(DIV_ASSIGN); }
"%="					{ return symbol(MOD_ASSIGN); }
"&="					{ return symbol(AND_ASSIGN); }
"^="					{ return symbol(XOR_ASSIGN); }
"|="					{ return symbol(OR_ASSIGN); }
">>"					{ return symbol(RIGHT_OP); }
"<<"					{ return symbol(LEFT_OP); }
"++"					{ return symbol(INC_OP); }
"--"					{ return symbol(DEC_OP); }
"->"					{ return symbol(PTR_OP); }
"&&"					{ return symbol(AND_OP); }
"||"					{ return symbol(OR_OP); }
"<="					{ return symbol(LE_OP); }
">="					{ return symbol(GE_OP); }
"=="					{ return symbol(EQ_OP); }
"!="					{ return symbol(NE_OP); }
";"						{ return symbol(SEMICOLON); }
"{"						{ return symbol(L_CURLY_BRACKET_LITERAL); }
"<%"					{ return symbol(L_CURLY_BRACKET_LITERAL); }
"}"						{ return symbol(R_CURLY_BRACKET_LITERAL); }
"%>"					{ return symbol(R_CURLY_BRACKET_LITERAL); }
","						{ return symbol(COMMA); }
":"						{ return symbol(COLON_LITERAL); }
"="						{ return symbol(EQUAL_LITERAL); }
"("						{ return symbol(L_ROUND_BRACKET); }
")"						{ return symbol(R_ROUND_BRACKET); }
"["						{ return symbol(L_SQUARE_BRACKET); }
"<:"					{ return symbol(L_SQUARE_BRACKET); }
"]"						{ return symbol(R_SQUARE_BRACKET); }
":>"					{ return symbol(R_SQUARE_BRACKET); }
"."						{ return symbol(POINT); }
"&"						{ return symbol(AMPERSAND_LITERAL); }
"!"						{ return symbol(EXCLAMATION_LITERAL); }
"~"						{ return symbol(TILDE_LITERAL); }
"-"						{ return symbol(MINUS_LITERAL); }
"+"						{ return symbol(ADD_LITERAL); }
"*"						{ return symbol(MUL_LITERAL); }
"/"						{ return symbol(SLASH_LITERAL); }
"%"						{ return symbol(PERCENT_LITERAL); }
"<"						{ return symbol(LESS_THAN_LITERAL); }
">"						{ return symbol(GREATER_THAN_LITERAL); }
"^"						{ return symbol(CARET_LITERAL); }
"|"						{ return symbol(PIPE_LITERAL); }
"?"						{ return symbol(QUESTION_LITERAL); }

{ident}					{ return symbol(IDENTIFIER, yytext()); }
{constante}           	{ return symbol(CONSTANT, yytext()); }
{white_space}     		{ /* ignore */ }
{Comment}				{ /* ignore */ }

}

<STRING> {
  \"                             { yybegin(YYINITIAL); 
                                   return symbol(STRING_LITERAL, string);
                                 }
  [^\n\r\"\\]+                   { string.append( yytext() ); }
  \\t                            { string.append('\t'); }
  \\n                            { string.append('\n'); }

  \\r                            { string.append('\r'); }
  \\\"                           { string.append('\"'); }
  \\                             { string.append('\\'); }
}


/* error fallback */
.|\n              {  /* throw new Error("Illegal character <"+ yytext()+">");*/
		    error("Illegal character <"+ yytext()+">");
                  }
